#include "processPool.h"
#include "tools.h"

int main(int argc, char* argv[])
{
    // sudo ./server ./conf/server.conf
    ARGS_CHECK(argc, 2);

    //加载服务器的配置，ip，port，processNum
    char ip[16];
    memset(ip,'\0',sizeof(ip));
    uint16_t port;
    int psNum;
    load_config_file(argv[1], ip, &port, &psNum);
    printf("ip = %s, port = %d, processNum = %d\n", ip, port, psNum);

    processPool_t pool; //栈上申请的内存
    struct epoll_event* pevtList; 
    //pool.processNum = atoi(argv[3]);
    pool.processNum = psNum;

    //构造函数    
    //最开始申请好了进程池的大小 和 epoll的就绪链表，按MAXCONNS分配的内存
    processPool_tInit(&pool, &pevtList);

    //1、创建N个子进程
    makeChild(&pool);

    //2、创建listen套接字，等待客户端的到来
    //argv[1],作为服务器
    //int listenfd = tcpServerInit(argv[1], atoi(argv[2]));
    int listenfd = tcpServerInit(ip, port);
    ERROR_CHECK(listenfd, -1, "listenfd");
    printf("listenfd = %d\n", listenfd);

    //3、创建epoll的实例，并注册相应的fd
    int epfd = epoll_create1(0);
    ERROR_CHECK(epfd, -1, "epoll_create1");
    printf("epfd = %d\n", epfd);
    epollAddEvent(epfd, listenfd, EPOLLIN);

    //这里监听的是管道pipe的读事件，不是客户client的s-----注意
    for (int i = 0; i < pool.processNum; i++) {
        //epoll的对象epfd，服务端socket的对象listenfd
        //
        epollAddEvent(epfd, pool.proChild[i].pipefd, EPOLLIN);
    }//监听（注册）是往红黑树上添加

    int nready = 0;
    while (1) {//事件循环
        do {
            nready = epoll_wait(epfd, pevtList, MAXCONNS, 5000);
        }while (-1 == nready && errno == EINTR);
        if (0 == nready) {
            //puts(">> epoll timeout.\n");
            continue;
        }
        else if (-1 == nready) {
            perror("epoll_wait");
            return EXIT_FAILURE;
        }
        else {
            //有事件发生
            eventsHappen(nready, pevtList, listenfd,  &pool);
        }

    }
    //管道fd程序结束时
    //peerfd, 未监听client，不知道何时断开的连接
    close(listenfd);
    close(epfd);
    //析构函数
    processPool_tDestroy(&pool, pevtList);
    return 0;
}
